// 云函数入口文件
const cloud = require('wx-server-sdk')

cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV });
const db = cloud.database({
  throwOnNotFound: false
})
const _ = db.command
const $ = db.command.aggregate

// 金额变动 ref balance
async function transferBalance(payer_id, payee_id, num, remark) {
  const modified_time = new Date().getTime();
  const tran = await db.startTransaction();
  // check Price
  const payer = (await tran.collection('tb_balance').doc(payer_id).get()).data;
  if (payer.current_balance < num) return { errMsg: '金额不足以支付' }
  // compute changed balance
  const payer_balance = payer.current_balance - num;
  const payee_balance = (await tran.collection('tb_balance').doc(payee_id).get()).data.current_balance + num;
  // payer
  await tran.collection('tb_balance').doc(payer_id)
    .update({ data: { current_balance: _.inc(-num), modified_time } })
  // payee
  await tran.collection('tb_balance').doc(payee_id)
    .update({ data: { current_balance: _.inc(num), modified_time } })
  await tran.commit()
  await db.collection('tb_balance_change').add({
    data: {
      change_balance: num,
      payer_balance,
      payee_balance,
      modified_time,
      remark,
      payee_id,
      payer_id,
    }
  })
  return { errMsg: '' }
}

async function addCoupon(order_id) {
  const res = await db.collection('tb_order').doc(order_id).get();
  const appointment_id = res.data.appointment_id;
  const end_time = parseInt(appointment_id.substring(appointment_id.lastIndexOf('-') + 1)) * 1e5;
  const start_time = new Date().getTime();
  const promiseArr = []
  res.data.sku_list.forEach((o, i) => {
    promiseArr.push(
      new Promise(resolve => {
        db.collection('tb_coupon').add({
          data: {
            order_id,
            coupon_state: 0,
            start_time,
            end_time: end_time - 8 * 3600000 + (o.rid + 1) * 30 * 60000,
            sku: { court_id: o.court_id, rid: o.rid },
            price: res.data.price_list[i]
          }
        }).then(r => resolve(r))
      })
    );
  })
  await Promise.all(promiseArr);
  return { errMsg: '' }
}

async function searchCouponList(searchData) {
  const res = await db.collection('tb_coupon').aggregate()
    .match(searchData)
    .lookup({
      from: 'tb_court',
      localField: 'sku.court_id',
      foreignField: '_id',
      as: 'court',
    })
    .limit(200)
    .end()
  return res.list;
}

async function updateCoupon(coupon_id, updData) {
  await db.collection('tb_coupon').doc(coupon_id)
    .update({ data: updData })
}

function checkCouponStatus(coupon_list) {
  let hasUsable = 0, hasVerify = 0;
  coupon_list.forEach(o => {
    if (o.coupon_state == 0) ++hasUsable;
    if (o.coupon_state == 1) ++hasVerify;
  })
  if (hasUsable) {
    return 2;
  } else if (hasVerify == coupon_list.length) {
    return 3;
  }
  return 1;
}

// 退款
async function refundCoupon(user_id, order_id, coupon_ids, remark) {
  const promiseArr = [];
  coupon_ids.forEach((coupon_id) => {
    promiseArr.push(
      new Promise(resolve => {
        db.collection('tb_coupon').doc(coupon_id).update({
          data: { coupon_state: 2 }
        }).then(r => resolve({ coupon_id, updated: r.stats.updated }))
      })
    )
  })
  await Promise.all(promiseArr);
  // 订单状态变动
  const couponList = (await db.collection('tb_coupon').where({ order_id }).get()).data;
  await db.collection('tb_order').doc(order_id).update({ data: { order_state: checkCouponStatus(couponList) } })
  // 退款
  const price = couponList.reduce((tot, cur) => (tot + cur.price), 0);
  await transferBalance('<system>', user_id, price * 100, remark);
  return { errMsg: '' }
}

// 核销
async function verifyCoupon(order_id, coupon_ids, remark) {
  const promiseArr = [];
  coupon_ids.forEach((coupon_id) => {
    promiseArr.push(
      new Promise(resolve => {
        db.collection('tb_coupon').doc(coupon_id).update({
          data: { coupon_state: 1 }
        }).then(r => resolve({ coupon_id, updated: r.stats.updated }))
      })
    )
  })
  await Promise.all(promiseArr);
  // 订单状态变动
  const couponList = (await db.collection('tb_coupon').where({ order_id }).get()).data;
  const order_state = checkCouponStatus(couponList);
  const order = (await db.collection('tb_order').doc(order_id).get()).data;
  const stadium_id = order.appointment_id.substring(0, order.appointment_id.lastIndexOf('-'));
  const payee_id = (await db.collection('tb_stadium').doc(stadium_id).get()).data.employer_id;
  if (order.order_state != order_state) {
    await db.collection('tb_order').doc(order_id).update({ data: { order_state } })
  }
  // 核销金额从系统三方转到财务
  const price = couponList.reduce((tot, cur) => (tot + cur.price), 0);
  await transferBalance('<system>', payee_id, price * 100, remark);
  return { errMsg: '' }
}

// 云函数入口函数
exports.main = async (event, context) => {
  const wxContext = cloud.getWXContext(), openid = wxContext.OPENID;

  if (event.funcName == 'insert') {
    return await addCoupon(event.order_id);
  } else if (event.funcName == 'query') {
    return await searchCouponList(event.searchData);
  } else if (event.funcName == 'update') {
  } else if (event.funcName == 'refund') {
    return await refundCoupon(openid, event.order_id, event.coupon_ids, event.remark);
  } else if (event.funcName == 'verify') {
    return await verifyCoupon(event.order_id, event.coupon_ids, event.remark)
  }
  return {
    event,
    // appid: wxContext.APPID,
    // unionid: wxContext.UNIONID,
  }
}